/*
 * Copyright 2019-2029 geekidea(https://github.com/geekidea)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.ts.enterprise.common.response;

import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * REST API 返回结果
 * </p>
 *
 * @author geekidea
 * @since 2018-11-08
 */
@Data
@Accessors(chain = true)
@Builder
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class ApiResult<T> implements Serializable {
    private static final long serialVersionUID = 8004487252556526569L;

    /**
     * 响应码
     */
    private Integer code;

    /**
     * 前端判断响应码
     */
    private Integer logicCode;


    /**
     * 响应消息
     */
    private String msg;

    /**
     * 响应数据
     */
    private T data;
    /**
     * 响应时间
     */
    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date time;

    public ApiResult() {
        time = new Date();
    }

    public static ApiResult<Boolean> result(boolean flag) {
        if (flag) {
            return success();
        }
        return failed();
    }

    public static ApiResult<Boolean> result(ApiCode apiCode) {
        return result(apiCode, null);
    }

    public static <T> ApiResult<T> result(ApiCode apiCode, T data) {
        return result(apiCode, null, data);
    }

    public static <T> ApiResult<T> result(Integer errorCode, String message, T data) {
        return (ApiResult<T>) ApiResult.builder()
                .code(errorCode)
                .msg(message)
                .data(data)
                .time(new Date())
                .build();
    }

    private static <T> ApiResult<T> result(ApiCode apiCode, String message, T data) {
        return (ApiResult<T>) ApiResult.builder()
                .code(apiCode.getCode())
                .msg(message)
                .data(data)
                .time(new Date())
                .build();
    }

    public static ApiResult<Boolean> success() {
        return success(null);
    }

    public static <T> ApiResult<T> success(T data) {
        return result(ApiCode.SUCCESS, data);
    }

    public static <T> ApiResult<T> success(T data, String message) {
        return result(ApiCode.SUCCESS, message, data);
    }

    public static ApiResult<Map<String, Object>> okMap(String key, Object value) {
        Map<String, Object> map = new HashMap<>(1);
        map.put(key, value);
        return success(map);
    }

    public static ApiResult<Boolean> failed(ApiCode apiCode) {
        return result(apiCode, null);
    }

    public static ApiResult<String> failed(String message) {
        return result(ApiCode.FAIL, message, null);

    }

    public static <T> ApiResult<T> failed(Integer errorCode , String message, T data) {
        return result(errorCode, message, data);

    }

    public static <T> ApiResult<T> failed(ApiCode apiCode, T data) {
        if (ApiCode.SUCCESS == apiCode) {
            throw new RuntimeException("失败结果状态码不能为" + ApiCode.SUCCESS.getCode());
        }
        return result(apiCode, data);

    }

    public static <T> ApiResult<T> failed(ApiCode apiCode, String message) {
        if (ApiCode.SUCCESS == apiCode) {
            throw new RuntimeException("失败结果状态码不能为" + ApiCode.SUCCESS.getCode());
        }
        return new ApiResult<T>()
                .setCode(apiCode.getCode())
                .setMsg(message);

    }

    public static ApiResult<String> failed(Integer code, String message) {
        return new ApiResult<String>()
                .setCode(code)
                .setMsg(message);
    }

    public static ApiResult<String> failed(Integer code, String message, Integer logicCode) {
        return new ApiResult<String>()
                .setCode(code)
                .setLogicCode(logicCode)
                .setMsg(message);
    }

    public static ApiResult<Map<String, Object>> failed(String key, Object value) {
        Map<String, Object> map = new HashMap<>(1);
        map.put(key, value);
        return result(ApiCode.FAIL, map);
    }

    public static ApiResult<Boolean> failed() {
        return failed(ApiCode.FAIL);
    }

}
